﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SQLManager;

namespace StockEOD
{
    public class Analyzer
    {
        public static event StatusMessageDelgate OnStatusMessage;
        //public static List<DailyDetail> GetBestPerformers(int daysBack)
        //{
        //    StocksDbDataContext context = new StocksDbDataContext();
        //    List<Market> markets =  context.Markets.ToList();
        //    List<DailyDetail> bestDD = new List<DailyDetail>();

        //    foreach (Market m in markets)
        //    {
        //        if (OnStatusMessage != null)
        //        {
        //            OnStatusMessage(String.Format("Loading market data for {0} .", m.Name));
        //        }
        //        ExtendedDailyDetail currentBest = new ExtendedDailyDetail(){ Ticker="NotSet", Open =double.MinValue  , Close= Double.MinValue,  Market = m, PercentagePriceChange=0};
               
        //        var qMD =(from md in context.MarketDays
        //              orderby md.Date descending
        //              where md.Market.Name == m.Name
        //              select md).Take(daysBack);
        //        List<MarketDay> days = qMD.ToList();
        //        MarketDay firstDay = days[0];
                
        //        DateTime lDate = firstDay.Date.Subtract(new TimeSpan(daysBack,0,0,0,0));
        //        //MarketDay lastDay = new MarketDay(){ Date= lDate, Market= firstDay.Market};
        //        var qDDFirst = (from dd in context.DailyDetails
        //                        where dd.Market.Name == m.Name && dd.Date == firstDay.Date
        //                        select dd);

        //        double pricechange = double.MinValue;
        //        if (OnStatusMessage != null)
        //        {
        //            OnStatusMessage(String.Format("Searching {0} for largest gains between {1} minus {2} days.", m.Name, firstDay.Date, daysBack));
        //        }
        //        DailyDetail ddLast = null;
        //        foreach (DailyDetail ddFirst in qDDFirst)
        //        {
                    
        //            // get the daily detail item from the qDDLast list that matches the current ddFirst one
        //            ddLast = FindNearestStartingDetail(m, daysBack, context, ddFirst.Ticker);
        //        if (ddLast!= null)
        //        {
        //            if (((ddFirst.Close - ddLast.Close) / ddLast.Close) > currentBest.PercentagePriceChange)
        //            {

        //                currentBest = new ExtendedDailyDetail() { High = ddLast.High, Low = ddLast.Low, Market = ddLast.Market, Ticker = ddLast.Ticker, Open = ddLast.Open, Close = ddLast.Open, Date = ddLast.Date, Vol = ddLast.Vol };
        //                currentBest.PercentagePriceChange = ((ddFirst.Close - ddLast.Close) / ddLast.Close);
        //                currentBest.RangeStarteDate = ddLast.Date;
        //                if (OnStatusMessage != null)
        //                {
        //                    OnStatusMessage(string.Format("Highest ROI found {0} {1}% @ {2} ",currentBest.Ticker,Math.Round( (double)currentBest.PercentagePriceChange *100,2),currentBest.Close));
        //                }

        //            }
        //        }
              
        //        else
        //        {
        //            if (OnStatusMessage != null)
        //            {
        //                OnStatusMessage(String.Format("Could not find data point for {0} {1} {2}",ddFirst.Market.Name,  ddFirst.Ticker, daysBack));
        //            }

        //        }
        //        }
        //        bestDD.Add(currentBest);
        //    }
        //    return bestDD;
        //}

        //public static void CreateDailyStatsAll()
        //{
        //    StocksDbDataContext context = new StocksDbDataContext();
        //    List<Market> markets = context.Markets.ToList();
            
        //    foreach (Market m in markets)
        //    {
        //        foreach (MarketDay md in m.MarketDays)
        //        {
        //            CreateMDStat(context, md, m);
        //        }
                

        //    }
        //    // Sumbit all stats
        //    context.SubmitChanges();
        //}
        //public static void CreateDailyStatsToday()
        //{
        //    StocksDbDataContext context = new StocksDbDataContext();
           
        //    List<Market> markets = context.Markets.ToList();
        //    foreach (Market m in markets)
        //    {

        //        MarketDay mdCurrent = FindMDByDaysBack(0, m, DateTime.Now);
        //        CreateMDStat(context, mdCurrent, m);

        //    }
        //    // Sumbit all stats
        //    context.SubmitChanges();
        //}
        //public static void CreateMDStat(StocksDbDataContext context, MarketDay mdCurrent, Market m)
        //{
        //    MarketDay mdWorking;

        //    DailyDetail ddPrior;
        //    if (mdCurrent != null)
        //    {
        //        // Loop through the stocks.
        //        var qDetails = m.DailyDetails.Where(dd => dd.Date == mdCurrent.Date);
        //        foreach (DailyDetail dd in qDetails)
        //        {
        //            DailyStatsPerStock stats = FindOrCreateStats(dd);
        //            // Calculate the 1DPC by Stock
        //            mdWorking = FindMDByDaysBack(1, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                //ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                //if (ddPrior != null)
        //                //{
        //                stats._1DPC = 100 * (dd.Close - dd.Open) / dd.Open;
        //                //}
        //            }
        //            // Calculate the 2DPC by stock
        //            mdWorking = FindMDByDaysBack(2, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                if (ddPrior != null)
        //                {
        //                    stats._2DPC = 100 * (dd.Close - ddPrior.Open) / ddPrior.Open;
        //                }
        //            }
        //            // Calculate the 5DPC by stock
        //            mdWorking = FindMDByDaysBack(5, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                if (ddPrior != null)
        //                {
        //                    stats._5DPC = 100 * (dd.Close - ddPrior.Open) / ddPrior.Open;
        //                }
        //            }
        //            // Calculate the 10DPC by stock
        //            mdWorking = FindMDByDaysBack(10, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                if (ddPrior != null)
        //                {
        //                    stats._10DPC = 100 * (dd.Close - ddPrior.Open) / ddPrior.Open;
        //                }
        //            }
        //            // Calculate the 30DPC by stock
        //            mdWorking = FindMDByDaysBack(30, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                if (ddPrior != null)
        //                {
        //                    stats._30DPC = 100 * (dd.Close - ddPrior.Open) / ddPrior.Open;
        //                }
        //            }
        //            // Calculate the 90DPC by stock
        //            mdWorking = FindMDByDaysBack(90, m, dd.Date);
        //            if (mdWorking != null)
        //            {
        //                ddPrior = FindDDByDate(mdWorking.Date, dd.Ticker, m);
        //                if (ddPrior != null)
        //                {
        //                    stats._90DPC = 100 * (dd.Close - ddPrior.Open) / ddPrior.Open;
        //                }
        //            }
        //            PublishStatMessage(stats);

        //        }
        //    }
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dd"></param>
        /// <returns></returns>
        public static DailyStatsPerStock FindOrCreateStats(DailyDetail dd)
        {

            if (dd.DailyStatsPerStocks.Count == 0)
            {
                dd.DailyStatsPerStocks.Add( new DailyStatsPerStock(){DailyDetailId = dd.Id});
            }

            return dd.DailyStatsPerStocks.Single();


        }

        //public static DailyDetail FindDDByDate(DateTime d, string ticker, Market m )
        //{
        //    var qDDPrior = (from dd in m.DailyDetails
        //                    where dd.Date == d
        //                    && dd.Ticker == ticker
        //                    orderby dd.Date descending
        //                    select dd).Take(1);
        //    if (qDDPrior.Count() == 1)
        //    {
        //        return qDDPrior.Single();
        //    }
        //    else
        //        return null;
        //}

        //public static MarketDay FindMDByDaysBack(int daysBack, Market m, DateTime dWorking)
        //{
        //    DateTime lessThanDate = dWorking.Subtract(new TimeSpan(daysBack, 0, 0, 0));
        //    var qReqMD = (from md in m.MarketDays
        //                  orderby md.Date descending
        //                  where md.Date <= lessThanDate
        //                  select md).Take(1);
        //    if (qReqMD.Count() == 1)
        //    {
        //        return qReqMD.Single();
        //    }
        //    else return null;

        //}
        //public static void PublishStatMessage(DailyStatsPerStock stat)
        //{
        //    if (OnStatusMessage != null)
        //    {
        //        OnStatusMessage(string.Format("% Change {0} {1} 1Day : {2}, 2Day : {3}, 5Day : {4}, 30Day : {5}, 90Day: {6}", stat.DailyDetail.Market.Name,
        //            stat.DailyDetail.Ticker,
        //            stat._1DPC != null ? Math.Round((double)stat._1DPC, 2).ToString() : "?",
        //            stat._2DPC != null ? Math.Round((double)stat._2DPC, 2).ToString() : "?",
        //            stat._5DPC != null ? Math.Round((double)stat._5DPC, 2).ToString() : "?",
        //            stat._30DPC != null ? Math.Round((double)stat._30DPC, 2).ToString() : "?",
        //            stat._90DPC != null ? Math.Round((double)stat._90DPC).ToString() : "?"));
        //    }
        //}
        //public static DailyDetail FindNearestStartingDetail(Market m, int startDaysBack, StocksDbDataContext context, string Ticker )
        //{
        //    int offset = 0;
        //    DailyDetail dd = null;
        //    while(dd==null)
        //    {
        //        var qMD = (from md in context.MarketDays
        //                   orderby md.Date descending
        //                   where md.Market.Name == m.Name
        //                   && md.Date <= DateTime.Today.Subtract(new TimeSpan(startDaysBack + offset ,0,0,0)) 
        //                   select md);
               
        //        DateTime? minDate =  qMD.Max(d => d.Date);
        //        var qDDLast = (from ddItem in context.DailyDetails
        //                       where ddItem.Market.Name == m.Name
        //                       && ddItem.Date == minDate
        //                       && ddItem.Ticker == Ticker
        //                       select ddItem);
        //        if (qDDLast.Count() > 0)
        //        {
        //            return qDDLast.Single();

        //        }
        //        else
        //        {
        //            if (offset < qMD.Count())
        //            {
        //                offset++;
        //            }
        //            else return null;
                    
        //        }

        //    }
        //    return null;
        //}

    }
    
   
}





